package connectors;

import java.io.Serializable;
import java.util.List;
import java.util.Observable;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 * <p>
 * A helper class for interacting with the databases</p>
 *
 * @param <T> the type of entity to store and access in the database
 * @date 11/5/2013
 *
 * @author Gregg Roemhildt
 *
 */
public class EntityList<T extends Serializable> extends Observable {

    private List<T> entityList;
    private final String entityType;

    /**
     * default constructor - initializes the database and list for the entity
     * type. persistanceType must be in the persistence.xml file to work.
     *
     * @param p type of persistence entity
     */
    public EntityList(String p) {

        EntityManager entities;
        EntityManagerFactory entityFactory;
        entityType = p;
        //create the entities
        entityFactory = Persistence.createEntityManagerFactory(p);
        entities = entityFactory.createEntityManager();

        //connect to db
        entities.getTransaction().begin();

        //initialize the list
        Query q = entities.createQuery("SELECT e FROM " + entityType + " e");
        entityList = (List<T>) q.getResultList();

        //close the database connection
        entities.getTransaction().commit();
        entities.close();
        entityFactory.close();
        updateObservers();
    }

    /**
     * add - adds a new entity to the list and persistence db
     *
     * @param e entity
     */
    public void add(T e) {
        EntityManager entities;
        EntityManagerFactory entityFactory;
        //create the entities
        entityFactory = Persistence.createEntityManagerFactory(entityType);
        entities = entityFactory.createEntityManager();
        //connect to db
        entities.getTransaction().begin();
        entityList.add(e);
        entities.persist(e);
        entities.getTransaction().commit();
        entities.close();
        entityFactory.close();
        updateObservers();
    }

    /**
     * remove - removes an entity from the list and persistence db
     *
     * @param e entity to remove
     */
    public void remove(T e) {
        EntityManager entities;
        EntityManagerFactory entityFactory;
        //create the entities
        entityFactory = Persistence.createEntityManagerFactory(entityType);
        entities = entityFactory.createEntityManager();
        //connect to db
        entities.getTransaction().begin();

        entityList.remove(e);
        entities.remove(e);
        entities.getTransaction().commit();
        entities.close();
        entityFactory.close();
        updateObservers();
    }

    /**
     * remove - removes an entity from the list and persistence db
     *
     * @param add entity to add
     * @param remove entity to remove
     */
    public void update(T add, T remove) {
        remove(remove);
        add(add);
    }

    /**
     * getCount - returns the number of entities
     *
     * @return number of entities stored
     */
    public int getCount() {
        return entityList.size();
    }

    /**
     * getList
     *
     * @param i an index to the item in the list
     * @return an item from the list at index i
     * @require i <= entityList.size()
     */
    public T getItem(int i) {
        if (i > entityList.size()) {
            return null;
        }
        return entityList.get(i);
    }

    /**
     * updateObservers - notifies views that data has changed
     */
    public void updateObservers() {
        //notify view
        setChanged();
        notifyObservers(entityList);
    }

    /**
     *
     * @return this list of entities
     */
    public List getList() {
        return entityList;
    }
}
